//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using System.Security;

using Survey.Common;
using Survey.Common.Business;
using Survey.Common.Validation;
using Survey.Entity;

using ProjectBase.Core;

using Survey.Common.Business.Services;
using Survey.Common.Data.Services;
using Survey.Entity.Services;

namespace Survey.Business.Services
{
    /// <summary>
    ///     All Business checks for 'User' on CRUD operations
    ///     are nested and encapsulated in this UserFacade
    /// </summary>
    public class UserFacade : BaseFacade<User, int, UserFilter, IUserDao>, IUserFacade
    {
        #region members
        MembershipProvider _membershipProvider;
        MemberValidator _memberValidator;
        #endregion members

        #region IBaseFacade<T> override - FACTORY METHOD
        public override User CreateNew()
        {
            var entity = CreateNew("newLogin");
            // TODO preset entity
            entity.Login = string.Empty;
            entity.Roles.Add("RegisteredUser");
            return entity;
        }

        public virtual User CreateNew(string login)
        {
            var entity = new User
            {
                Login = login,
                LastName = login,
                FirstName = string.Empty
            };
            return entity;
        }
        #endregion IBaseFacade<T> override - FACTORY METHOD

        #region Membership - GetById, Add, Update
        //public override User Add(User entity)
        //{
        //    MembershipCreateStatus status;

        //    entity.Member.FirstName = entity.FirstName;
        //    entity.Member.Surname = entity.LastName;
        //    entity.Member.UserName = entity.Login;

        //    if(!MemberValidator.ValidateAdd(this, entity.Member))
        //    {
        //        return entity;
        //    }

        //    MProvider.CreateUser(entity.Login, entity.Member.Password, entity.Member.Email, null, null, true, null, out status);
        //    if (status.Equals(MembershipCreateStatus.Success))
        //    {
        //        entity = base.Add(entity);
        //    }
        //    else
        //    {
        //        this.PublishError(status.ToString());
        //    }
        //    return entity;
        //}

        //public override User Update(User entity)
        //{
        //    entity = base.Update(entity);
        //    if (Messages.ContainsError())
        //    {
        //        return entity;
        //    }


        //    entity.Member.FirstName = entity.FirstName;
        //    entity.Member.Surname = entity.LastName;
        //    entity.Member.UserName = entity.Login;


        //    if (!MemberValidator.ValidateUpdate(this, entity.Member))
        //    {
        //        return entity;
        //    }


        //    var currentUser = MProvider.GetUser(entity.Login, false);
        //    if(currentUser.IsNull() || entity.Member.IsNull())
        //    {
        //        return entity;
        //    }

        //    // update Email
        //    if (entity.Member.Email.Is()
        //        && !entity.Member.Email.Equals(currentUser.Email))
        //    {
        //        currentUser.Email = entity.Member.Email.IsNotEmpty()
        //            ? entity.Member.Email
        //            : currentUser.Email;
        //        MProvider.UpdateUser(currentUser);
        //    }

        //    entity.Member.Password = entity.Member.NewPassword;
        //    if (entity.Member.Password.IsNotEmpty()
        //        && entity.Member.ConfirmedPassword.IsNotEmpty())
        //    {
        //        // update password
        //        var pwd = currentUser.ResetPassword(entity.Member.Password);
        //        currentUser.ChangePassword(pwd, entity.Member.Password);
        //    }
        //    return entity;
        //}

        //public override void Delete(User entity)
        //{
        //    Membership.DeleteUser(entity.Login);
        //    base.Delete(entity);
        //}
        #endregion Membership - override GetById, Add, Update

        #region Membership - Bind
        //public override bool BindEntity(User entity, IValueProvider valueProvider, string prefix = null)
        //{
        //    entity.Roles = new List<string>(entity.Roles.Where(r => !r.Equals(string.Empty)));
        //    BindMember(entity, valueProvider, "Member");
        //    return base.BindEntity(entity, valueProvider, prefix);
        //}
        //protected virtual bool BindMember(User entity, IValueProvider valueProvider, string prefix = null)
        //{
        //    Binder.Bind(entity.Member, valueProvider, prefix);
        //    return true;
        //}
        #endregion Membership - Bind

        #region constructor
        static UserFacade()
        {
            ChangeHandler += Clear;
        }
        #endregion constructor

        #region IUserFacade
        public virtual User GetByLogin(string login)
        {
            if (login.IsEmpty())
            {
                return null;
            }

            var username = GetUserName(login);
            var users = GetAllUsers();

            return users.ContainsKey(username)
                ? users[username]
                : null;
        }

        public virtual void Clear()
        {
            Clear(this, null);
        }
        #endregion IUserFacade

        #region Membership
        public bool ValidateUser(string userName, string password)
        {
            return Membership.ValidateUser(userName, password);
        }

        public MembershipCreateStatus CreateMember(Member member)
        {
            if (!MemberValidator.Validate(member, ValidateOn.Add, this))
            {
                return MembershipCreateStatus.UserRejected;
            }

            MembershipCreateStatus status;
            MProvider.CreateUser(member.UserName, member.Password, member.Email, null, null, true, null, out status);
            if (status.Equals(MembershipCreateStatus.Success))
            {
                var user = CreateNew(member.UserName);
                user.FirstName = member.FirstName;
                user.LastName = member.Surname;
                user.Roles.Add("RegisteredUser");
                user.Roles.Add("Viewer");
                user.CurrentRole = user.Roles.First();
                Add(user);
            }
            else
            {
                this.PublishError(status.ToString());
            }
            return status;
        }

        public bool UpdateMember(Member member)
        {
            if (!MemberValidator.Validate(member, ValidateOn.Update, this))
            {
                return false;
            }

            try
            {
                // update user
                var entity = GetByLogin(member.UserName);
                entity.FirstName = member.FirstName;
                entity.LastName = member.Surname;

                Update(entity);
                if (Messages.ContainsError())
                {
                    return false;
                }

                // update password
                var currentUser = MProvider.GetUser(member.UserName, true /* userIsOnline */);
                return member.NewPassword.IsEmpty()
                    || currentUser.ChangePassword(member.Password, member.NewPassword);
            }
            catch (ArgumentException ex)
            {
                this.PublishFatal(ex);
                return false;
            }
            catch (MembershipPasswordException ex)
            {
                this.PublishFatal(ex);
                return false;
            }
        }

        public override string ValidationRulesToString(string filter = null)
        {
            if (filter.IsNotEmpty())
            {
                if (filter.IsEqual(Str.Business.Services.Register))
                {
                    return MemberValidator.ValidationRulesToString(Str.Actions.NoView.Add);
                }
                if (filter.IsEqual(Str.Business.Services.Change))
                {
                    return MemberValidator.ValidationRulesToString(Str.Actions.NoView.Update);
                }
            }
            return base.ValidationRulesToString(filter);
        }
        #endregion Membership

        #region protected
        protected static IDictionary<string, User> Users { get; set; }

        static string GetUserName(string login)
        {
            if (login.Is()
                && login.Contains('\\'))
            {
                return login.Split('\\')[1].ToLowerInvariant();
            }
            return login.ToLowerInvariant();
        }

        protected virtual IDictionary<string, User> GetAllUsers()
        {
            CheckFileDependency();

            var users = Users;
            if (users.IsNull())
            {
                this.PublishDebug("User's GetAllUsers() static cache reloaded");
                users = new Dictionary<string, User>();
                var list = Dao.GetAll();
                foreach (var user in list)
                {
                    var clone = user.Clone() as User;
                    users[user.Login.ToLowerInvariant()] = clone;

                }
                Users = users;
            }
            return users;
        }

        static void Clear(object sender, EventArgs e)
        {
            Users = null;
        }
        #endregion protected

        #region properties

        public virtual MembershipProvider MProvider
        {
            get { return _membershipProvider ?? Membership.Provider; }
            set { _membershipProvider = value; }
        }
        public virtual MemberValidator MemberValidator
        {
            get { return _memberValidator ?? (_memberValidator = new MemberValidator()); }
            set { _memberValidator = value; }
        }
        #endregion properties
    }
}